#ifndef ____SSBASEL__SSBASE__BASE_SCOPED_PTR__H__
#define ____SSBASEL__SSBASE__BASE_SCOPED_PTR__H__

#include "base.h"

_SSL_BEGIN
_SSBASEL_BEGIN

template <class C>
class scoped_ptr
{
private:
	struct r_value : public scoped_ptr
	{
		r_value();
		~r_value();
		r_value(const r_value&);
		void operator=(const r_value&);
	};
	scoped_ptr(scoped_ptr&);
	void operator=(scoped_ptr&);

public:
	operator r_value&() { return *reinterpret_cast<r_value*>(this); }
	scoped_ptr Pass() { return scoped_ptr(*reinterpret_cast<r_value*>(this)); }

	typedef C element_type;

	explicit scoped_ptr(C* p = NULL) : ptr_(p) { }

	template <typename U>
	scoped_ptr(scoped_ptr<U> other) : ptr_(other.release()) { }

	scoped_ptr(r_value& other) : ptr_(other.release()) { }

	~scoped_ptr()
	{
		enum { type_must_be_complete = sizeof(C) };
		delete ptr_;
	}

	template <typename U>
	scoped_ptr& operator=(scoped_ptr<U> rhs)
	{
		reset(rhs.release());
		return *this;
	}

	scoped_ptr& operator=(r_value& rhs)
	{
		swap(rhs);
		return *this;
	}

	void reset(C* p = NULL)
	{
		if (p != ptr_) {
			enum { type_must_be_complete = sizeof(C) };
			delete ptr_;
			ptr_ = p;
		}
	}

	C& operator*() const
	{
		return *ptr_;
	}
	C* operator->() const
	{
		return ptr_;
	}
	C* get() const { return ptr_; }

	bool operator==(C* p) const { return ptr_ == p; }
	bool operator!=(C* p) const { return ptr_ != p; }

	void swap(scoped_ptr& p2)
	{
		C* tmp = ptr_;
		ptr_ = p2.ptr_;
		p2.ptr_ = tmp;
	}

	C* release()
	{
		C* retVal = ptr_;
		ptr_ = NULL;
		return retVal;
	}

	template <typename PassAsType>
	scoped_ptr<PassAsType> PassAs()
	{
		return scoped_ptr<PassAsType>(release());
	}

private:
	C* ptr_;

	// disable object compare
	template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
	template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
};

template <class C>
void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2)
{
	p1.swap(p2);
}

template <class C>
bool operator==(C* p1, const scoped_ptr<C>& p2)
{
	return p1 == p2.get();
}

template <class C>
bool operator!=(C* p1, const scoped_ptr<C>& p2)
{
	return p1 != p2.get();
}

_SSBASEL_END
_SSL_END

#endif
